﻿#ifndef _NLIST_H_
#define _NLIST_H_

#include "sys_plat.h"
#include <stdlib.h>
#include <stdbool.h>

typedef struct _nlist_node_t
{
    struct _nlist_node_t *pre;
    struct _nlist_node_t *next;
} nlist_node_t;

typedef struct _nlist_t
{
    struct _nlist_node_t *first;
    struct _nlist_node_t *last;
    int count;
} nlist_t;

// 获取节点在通用结构中的偏移量
#define noffset_in_parent(parent_type, node_name) ((char *)(&(((parent_type *)0)->node_name)))

// 根据节点获取通用结构的首地址
#define noffset_to_parent(parent_type, node_name, node_addr) ((parent_type *)((char *)(node_addr) - (noffset_in_parent(parent_type, node_name))))

/**
 * @brief 根据node位置获取整个结构体的位置
 * @param paren_type 结构体类型名
 * @param node_name 节点在该结构体中的名称
 * @param node_addr 节点地址
 */
#define nlist_entry(parent_type, node_name, node_addr) ((node_addr) ? noffset_to_parent(parent_type, node_name, node_addr) : (parent_type *)0)

// 从前往后遍历链表
#define nlist_for_each(curr_p, nlist_p) for ((curr_p) = (nlist_p)->first; (curr_p); (curr_p) = (curr_p)->next)

// 从后往前遍历通用链表
#define nlist_for_each_reverse(curr_p, nlist_p) for (curr_p = nlist_p->last; curr_p; curr_p = curr_p->pre)

static inline void nlist_node_init(nlist_node_t *node)
{
    if (node)
    {
        node->pre = NULL;
        node->next = NULL;
    }
}

static inline nlist_node_t *nlist_node_next(const nlist_node_t *node)
{
    return node->next;
}

static inline nlist_node_t *nlist_node_pre(const nlist_node_t *node)
{
    return node->pre;
}

static inline void nlist_node_set_next(nlist_node_t *pre, nlist_node_t *next)
{
    pre->next = next;
    next->pre = pre;
}

static inline void nlist_init(nlist_t *nlist)
{
    if (nlist)
    {
        nlist->first = NULL;
        nlist->last = NULL;
        nlist->count = 0;
    }
}

static inline int nlist_count(const nlist_t *nlist)
{
    if (nlist)
    {
        return nlist->count;
    }
    return 0;
}

static inline bool nlist_is_empty(nlist_t *nlist)
{
    if (nlist)
    {
        return nlist->count == 0;
    }
    return true;
}

static inline nlist_node_t *nlist_first(nlist_t *nlist)
{
    if (nlist)
    {
        return nlist->first;
    }
    return NULL;
}

static inline nlist_node_t *nlist_last(nlist_t *nlist)
{
    if (nlist)
    {
        return nlist->last;
    }
    return NULL;
}

void nlist_insert_first(nlist_t *nlist, nlist_node_t *node);
void nlist_insert_last(nlist_t *nlist, nlist_node_t *node);
void nlist_insert_after(nlist_t *nlist, nlist_node_t *pre, nlist_node_t *node);
nlist_node_t *nlist_remove(nlist_t *nlist, nlist_node_t *node);

static inline nlist_node_t *nlist_remove_first(nlist_t *nlist)
{
    return nlist_remove(nlist, nlist->first);
}

static inline nlist_node_t *nlist_remove_last(nlist_t *nlist)
{
    return nlist_remove(nlist, nlist->last);
}
#endif